<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>限流算法可视化解析 - 高并发系统稳定性的守护者</title>
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8fafc;
            color: #1e293b;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
        }
        .code-block {
            background-color: #1e293b;
            border-radius: 0.5rem;
        }
        .algorithm-card:hover {
            transform: translateY(-4px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .highlight {
            position: relative;
        }
        .highlight:after {
            content: '';
            position: absolute;
            bottom: 2px;
            left: 0;
            width: 100%;
            height: 6px;
            background-color: #a5b4fc;
            opacity: 0.5;
            z-index: -1;
            transition: all 0.3s ease;
        }
        .highlight:hover:after {
            height: 12px;
            opacity: 0.8;
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 px-4 md:py-32">
        <div class="container mx-auto max-w-6xl">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-1/2 mb-10 md:mb-0">
                    <h1 class="text-4xl md:text-5xl font-bold mb-6 leading-tight font-serif">限流算法解密：<br>高并发系统的守护卫士</h1>
                    <p class="text-xl mb-8 opacity-90 leading-relaxed">探索令牌桶与漏桶算法如何为系统构筑流量防线，在汹涌请求中维持稳定运行</p>
                    <div class="flex space-x-4">
                        <a href="#token-bucket" class="bg-white text-indigo-600 px-6 py-3 rounded-full font-medium hover:bg-indigo-50 transition duration-300 flex items-center">
                            <i class="fas fa-coins mr-2"></i> 令牌桶算法
                        </a>
                        <a href="#leaky-bucket" class="bg-indigo-700 text-white px-6 py-3 rounded-full font-medium hover:bg-indigo-800 transition duration-300 flex items-center">
                            <i class="fas fa-faucet mr-2"></i> 漏桶算法
                        </a>
                    </div>
                </div>
                <div class="md:w-1/2">
                    <div class="mermaid bg-white p-6 rounded-xl shadow-xl">
                        graph TD
                            A[高并发请求] -->|流量控制| B{限流算法}
                            B --> C[令牌桶]
                            B --> D[漏桶]
                            C --> E[固定速率生成令牌]
                            C --> F[突发流量缓冲]
                            D --> G[固定速率处理]
                            D --> H[平滑流量]
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <div class="container mx-auto max-w-6xl px-4 py-16">
        <!-- 算法对比 -->
        <section class="mb-24">
            <h2 class="text-3xl font-bold mb-12 text-center font-serif">两大限流算法对比</h2>
            <div class="grid md:grid-cols-2 gap-8">
                <div class="bg-white p-8 rounded-xl shadow-md algorithm-card transition duration-300">
                    <div class="flex items-center mb-6">
                        <div class="bg-indigo-100 text-indigo-600 p-3 rounded-full mr-4">
                            <i class="fas fa-coins text-2xl"></i>
                        </div>
                        <h3 id="token-bucket" class="text-2xl font-bold">令牌桶算法</h3>
                    </div>
                    <div class="space-y-4">
                        <div class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <p>以固定速率生成令牌，请求需要消耗令牌</p>
                        </div>
                        <div class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <p>允许短暂的突发流量（当桶中有足够令牌时）</p>
                        </div>
                        <div class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <p>实现简单，时间复杂度O(1)</p>
                        </div>
                    </div>
                </div>
                <div class="bg-white p-8 rounded-xl shadow-md algorithm-card transition duration-300">
                    <div class="flex items-center mb-6">
                        <div class="bg-purple-100 text-purple-600 p-3 rounded-full mr-4">
                            <i class="fas fa-faucet text-2xl"></i>
                        </div>
                        <h3 id="leaky-bucket" class="text-2xl font-bold">漏桶算法</h3>
                    </div>
                    <div class="space-y-4">
                        <div class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <p>请求以固定速率流出，超过桶容量则丢弃</p>
                        </div>
                        <div class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <p>强制恒定的处理速率，使流量更平滑</p>
                        </div>
                        <div class="flex items-start">
                            <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                            <p>适用于需要严格控制处理速率的场景</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 令牌桶算法详解 -->
        <section class="mb-24">
            <div class="flex items-center mb-8">
                <h2 class="text-3xl font-bold font-serif">令牌桶算法详解</h2>
                <span class="ml-4 bg-indigo-100 text-indigo-800 text-sm font-medium px-3 py-1 rounded-full">突发流量友好</span>
            </div>
            
            <div class="grid md:grid-cols-2 gap-8 items-center mb-12">
                <div>
                    <p class="text-lg mb-6 leading-relaxed">令牌桶算法维护一个固定容量的<span class="highlight font-medium">"桶"</span>，系统以恒定速率向桶中添加<span class="highlight font-medium">"令牌"</span>。当请求到达时，需要从桶中获取一个令牌才能被处理。如果桶中没有足够的令牌，请求将被拒绝或排队等待。</p>
                    
                    <div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-info-circle text-blue-500 mt-1"></i>
                            </div>
                            <div class="ml-3">
                                <p class="text-blue-700"><span class="font-bold">核心优势：</span>允许系统处理短期的突发流量，只要桶中有足够的令牌储备。</p>
                            </div>
                        </div>
                    </div>
                    
                    <div class="flex flex-wrap gap-4">
                        <div class="bg-white shadow rounded-lg p-4 flex-1 min-w-[200px]">
                            <h4 class="font-bold text-gray-500 text-sm mb-2">时间复杂度</h4>
                            <p class="text-2xl font-bold">O(1)</p>
                        </div>
                        <div class="bg-white shadow rounded-lg p-4 flex-1 min-w-[200px]">
                            <h4 class="font-bold text-gray-500 text-sm mb-2">空间复杂度</h4>
                            <p class="text-2xl font-bold">O(1)</p>
                        </div>
                    </div>
                </div>
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <div class="mermaid">
                        graph LR
                            A[令牌生成器] -->|固定速率| B[令牌桶]
                            B -->|消耗令牌| C[请求处理]
                            C --> D{有令牌?}
                            D -->|是| E[处理请求]
                            D -->|否| F[拒绝请求]
                    </div>
                </div>
            </div>
            
            <h3 class="text-2xl font-bold mb-6 flex items-center">
                <i class="fas fa-code mr-3 text-indigo-500"></i> 
                Java实现代码
            </h3>
            <div class="code-block rounded-xl overflow-hidden shadow-lg mb-8">
                <div class="flex items-center bg-gray-800 px-4 py-3">
                    <div class="flex space-x-2 mr-4">
                        <div class="w-3 h-3 rounded-full bg-red-500"></div>
                        <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
                        <div class="w-3 h-3 rounded-full bg-green-500"></div>
                    </div>
                    <span class="text-gray-300 text-sm">TokenBucket.java</span>
                </div>
                <pre class="text-gray-200 p-6 overflow-x-auto"><code>/**
 * 令牌桶限流算法实现
 * 以固定速率向桶中添加令牌，请求需要消耗令牌才能被处理
 */
public class TokenBucket {
    // 桶的容量
    private final double capacity;
    // 当前令牌数量
    private double tokens;
    // 令牌生成速率（每秒）
    private final double rate;
    // 上次添加令牌的时间
    private long lastRefillTime;
    
    /**
     * 构造函数
     * @param capacity 桶的容量
     * @param rate 令牌生成速率（每秒）
     */
    public TokenBucket(double capacity, double rate) {
        this.capacity = capacity;
        this.tokens = capacity;  // 初始时桶是满的
        this.rate = rate;
        this.lastRefillTime = System.currentTimeMillis();
    }
    
    /**
     * 判断请求是否被允许处理
     * @return 如果有足够的令牌可用，返回true；否则返回false
     */
    public synchronized boolean allowRequest() {
        // 计算当前时间
        long now = System.currentTimeMillis();
        
        // 计算从上次添加令牌到现在经过的时间，并添加相应数量的令牌
        double newTokens = (now - lastRefillTime) / 1000.0 * rate;
        tokens = Math.min(capacity, tokens + newTokens);
        
        // 更新上次添加令牌的时间
        lastRefillTime = now;
        
        // 如果有足够的令牌，则消耗一个令牌并允许请求
        if (tokens >= 1) {
            tokens -= 1;
            return true;
        }
        
        // 没有足够的令牌，拒绝请求
        return false;
    }
}</code></pre>
            </div>
            
            <div class="bg-white p-6 rounded-xl shadow-md">
                <h4 class="font-bold text-lg mb-4 flex items-center">
                    <i class="fas fa-lightbulb text-yellow-500 mr-2"></i>
                    关键点解析
                </h4>
                <ul class="space-y-3">
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 rounded-full bg-indigo-100 text-indigo-600 flex items-center justify-center mr-3 mt-0.5">
                            <span class="text-xs font-bold">1</span>
                        </div>
                        <p><span class="font-medium">令牌生成</span>：系统以固定速率（rate）向桶中添加令牌，确保长期平均处理速率可控</p>
                    </li>
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 rounded-full bg-indigo-100 text-indigo-600 flex items-center justify-center mr-3 mt-0.5">
                            <span class="text-xs font-bold">2</span>
                        </div>
                        <p><span class="font-medium">突发处理</span>：当桶中有足够令牌时，系统可以短时间处理高于平均速率的请求</p>
                    </li>
                    <li class="flex items-start">
                        <div class="flex-shrink-0 h-6 w-6 rounded-full bg-indigo-100 text-indigo-600 flex items-center justify-center mr-3 mt-0.5">
                            <span class="text-xs font-bold">3</span>
                        </div>
                        <p><span class="font-medium">线程安全</span>：使用synchronized关键字确保多线程环境下的正确性</p>
                    </li>
                </ul>
            </div>
        </section>

        <!-- 漏桶算法详解 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <h2 class="text-3xl font-bold font-serif">漏桶算法详解</h2>
                <span class="ml-4 bg-purple-100 text-purple-800 text-sm font-medium px-3 py-1 rounded-full">流量平滑</span>
            </div>
            
            <div class="grid md:grid-cols-2 gap-8 items-center mb-12">
                <div>
                    <p class="text-lg mb-6 leading-relaxed">漏桶算法将请求想象为<span class="highlight font-medium">"水"</span>，流入一个底部有孔的桶中。无论流入速度如何，水都以<span class="highlight font-medium">固定速率</span>从孔中漏出（被处理）。如果桶已满，则新流入的水（请求）会溢出（被拒绝）。</p>
                    
                    <div class="bg-purple-50 border-l-4 border-purple-500 p-4 mb-6">
                        <div class="flex">
                            <div class="flex-shrink-0">
                                <i class="fas fa-info-circle text-purple-500 mt-1"></i>
                            </div>
                            <div class="ml-3">
                                <p class="text-purple-700"><span class="font-bold">核心特点：</span>强制恒定的处理速率，即使面对突发流量也能保持输出稳定，保护下游系统。</p>
                            </div>
                        </div>
                    </div>
                    
                    <div class="flex flex-wrap gap-4">
                        <div class="bg-white shadow rounded-lg p-4 flex-1 min-w-[200px]">
                            <h4 class="font-bold text-gray-500 text-sm mb-2">应用场景</h4>
                            <p class="font-medium">API限流、流量整形</p>
                        </div>
                        <div class="bg-white shadow rounded-lg p-4 flex-1 min-w-[200px]">
                            <h4 class="font-bold text-gray-500 text-sm mb-2">典型实现</h4>
                            <p class="font-medium">Nginx限流模块</p>
                        </div>
                    </div>
                </div>
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <div class="mermaid">
                        graph TB
                            A[请求流入] --> B[漏桶]
                            B -->|固定速率| C[请求处理]
                            B -->|桶满| D[拒绝请求]
                    </div>
                </div>
            </div>
            
            <h3 class="text-2xl font-bold mb-6 flex items-center">
                <i class="fas fa-code mr-3 text-purple-500"></i> 
                Java实现代码
            </h3>
            <div class="code-block rounded-xl overflow-hidden shadow-lg mb-8">
                <div class="flex items-center bg-gray-800 px-4 py-3">
                    <div class="flex space-x-2 mr-4">
                        <div class="w-3 h-3 rounded-full bg-red-500"></div>
                        <div class="w-3 h-3 rounded-full bg-yellow-500"></div>
                        <div class="w-3 h-3 rounded-full bg-green-500"></div>
                    </div>
                    <span class="text-gray-300 text-sm">LeakyBucket.java</span>
                </div>
                <pre class="text-gray-200 p-6 overflow-x-auto"><code>/**
 * 漏桶限流算法实现
 * 请求以固定速率流出，超过桶容量的请求会被丢弃
 */
public class LeakyBucket {
    // 桶的容量
    private final int capacity;
    // 当前桶中的水量（请求数）
    private int water;
    // 水流出速率（每秒处理的请求数）
    private final double rate;
    // 上次漏水的时间
    private long lastLeakTime;
    
    /**
     * 构造函数
     * @param capacity 桶的容量
     * @param rate 水流出速率（每秒）
     */
    public LeakyBucket(int capacity, double rate) {
        this.capacity = capacity;
        this.water = 0;
        this.rate = rate;
        this.lastLeakTime = System.currentTimeMillis();
    }
    
    /**
     * 判断请求是否被允许处理
     * @return 如果请求可以被处理，返回true；否则返回false
     */
    public synchronized boolean allowRequest() {
        // 计算当前时间
        long now = System.currentTimeMillis();
        
        // 计算从上次漏水到现在经过的时间，并计算漏出的水量
        int leakedWater = (int) ((now - lastLeakTime) / 1000.0 * rate);
        
        // 更新当前水量和上次漏水时间
        if (leakedWater > 0) {
            water = Math.max(0, water - leakedWater);
            lastLeakTime = now;
        }
        
        // 如果桶未满，则接收请求
        if (water < capacity) {
            water++;
            return true;
        }
        
        // 桶已满，拒绝请求
        return false;
    }
}</code></pre>
            </div>
            
            <div class="grid md:grid-cols-2 gap-8">
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <h4 class="font-bold text-lg mb-4 flex items-center">
                        <i class="fas fa-check-circle text-green-500 mr-2"></i>
                        适用场景
                    </h4>
                    <ul class="space-y-2">
                        <li class="flex items-start">
                            <i class="fas fa-arrow-right text-xs text-purple-500 mt-1 mr-2"></i>
                            <p>需要严格控制处理速率的API服务</p>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-arrow-right text-xs text-purple-500 mt-1 mr-2"></i>
                            <p>保护下游系统不被突发流量冲垮</p>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-arrow-right text-xs text-purple-500 mt-1 mr-2"></i>
                            <p>需要平滑流量的消息队列消费者</p>
                        </li>
                    </ul>
                </div>
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <h4 class="font-bold text-lg mb-4 flex items-center">
                        <i class="fas fa-times-circle text-red-500 mr-2"></i>
                        局限性
                    </h4>
                    <ul class="space-y-2">
                        <li class="flex items-start">
                            <i class="fas fa-arrow-right text-xs text-purple-500 mt-1 mr-2"></i>
                            <p>无法应对合法的突发流量需求</p>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-arrow-right text-xs text-purple-500 mt-1 mr-2"></i>
                            <p>较长的排队时间可能导致请求超时</p>
                        </li>
                    </ul>
                </div>
            </div>
        </section>

        <!-- 场景选择建议 -->
        <section class="bg-indigo-50 rounded-2xl p-8 md:p-12 mb-16">
            <h2 class="text-3xl font-bold mb-8 text-center font-serif">如何选择合适的限流算法？</h2>
            <div class="grid md:grid-cols-3 gap-8">
                <div class="bg-white p-6 rounded-xl shadow-sm">
                    <div class="text-indigo-600 text-4xl mb-4">
                        <i class="fas fa-bolt"></i>
                    </div>
                    <h3 class="font-bold text-xl mb-3">突发流量场景</h3>
                    <p class="text-gray-600">当系统需要处理合法的突发请求（如秒杀活动、抢购等），选择<span class="font-medium text-indigo-700">令牌桶算法</span>更合适，它可以利用积累的令牌处理突发流量。</p>
                </div>
                <div class="bg-white p-6 rounded-xl shadow-sm">
                    <div class="text-purple-600 text-4xl mb-4">
                        <i class="fas fa-tint"></i>
                    </div>
                    <h3 class="font-bold text-xl mb-3">平滑流量场景</h3>
                    <p class="text-gray-600">当需要严格控制处理速率，保护下游系统（如数据库、第三方API）时，<span class="font-medium text-purple-700">漏桶算法</span>能确保恒定的输出速率。</p>
                </div>
                <div class="bg-white p-6 rounded-xl shadow-sm">
                    <div class="text-blue-600 text-4xl mb-4">
                        <i class="fas fa-random"></i>
                    </div>
                    <h3 class="font-bold text-xl mb-3">混合策略</h3>
                    <p class="text-gray-600">在实际系统中，可以结合两种算法：外层使用令牌桶应对突发，内层使用漏桶平滑流量，达到既灵活又稳定的效果。</p>
                </div>
            </div>
        </section>
    </div>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
        
        // 微交互：代码块点击复制
        document.querySelectorAll('pre code').forEach((codeBlock) => {
            codeBlock.addEventListener('click', () => {
                const range = document.createRange();
                range.selectNode(codeBlock);
                window.getSelection().removeAllRanges();
                window.getSelection().addRange(range);
                document.execCommand('copy');
                window.getSelection().removeAllRanges();
                
                // 显示复制成功的提示
                const originalText = codeBlock.textContent;
                codeBlock.textContent = '代码已复制到剪贴板！';
                setTimeout(() => {
                    codeBlock.textContent = originalText;
                }, 1500);
            });
        });
    </script>
</body>
</html>